package com.xxx.control.net;

import android.util.Log;

import androidx.lifecycle.LifecycleOwner;

import com.uber.autodispose.AutoDispose;
import com.uber.autodispose.AutoDisposeConverter;
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider;

import org.reactivestreams.Publisher;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import io.reactivex.Flowable;
import io.reactivex.FlowableTransformer;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.SingleTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by Hasee on2019/8/31
 * Des: 对线程切换操作再做一个封装：RxScheduler
 */
public class RxScheduler {

    private static final String TAG = "RxScheduler";

    /**
     * 推荐使用：网络请求一般都是单事件请求  onNext和onComplete可以合起来使用
     *
     * @param <T>
     * @return Single转换器
     */
    public static <T> SingleTransformer<T, T> singleOnMainThread() {


        return new SingleTransformer<T, T>() {
            // 可重试次数
            private int maxConnectCount = 3;
            // 当前已重试次数
            private int currentRetryCount = 0;
            // 重试等待时间
            private int waitRetryTime = 0;

            @Override
            public SingleSource<T> apply(Single<T> upstream) {
                return upstream
                        .retryWhen(new Function<Flowable<Throwable>, Publisher<?>>() {
                            @Override
                            public Publisher<?> apply(Flowable<Throwable> throwableFlowable) throws Exception {
                                return throwableFlowable.flatMap(new Function<Throwable, Publisher<?>>() {
                                    @Override
                                    public Publisher<?> apply(Throwable throwable) throws Exception {
                                        if (throwable instanceof IOException) {
                                            if (currentRetryCount < maxConnectCount) {
                                                currentRetryCount++;// 记录重试次数
                                                /**
                                                 * 实现重试
                                                 * 通过返回的Observable发送的事件 = next事件，从而使得retryWhen（）重订阅，最终实现重试功能
                                                 * 延迟1段时间再重试 delay操作符 = 延迟一段时间发送
                                                 * 在delay操作符的等待时间内设置 = 每重试1次，增多延迟重试时间1s
                                                 */
                                                waitRetryTime = 1000 + currentRetryCount * 1000;
//                                                Timber.tag(TAG).e("重试次数:" + currentRetryCount + "--等待时间:" + waitRetryTime);
                                                return Flowable.just(1).delay(waitRetryTime, TimeUnit.MILLISECONDS);
                                            } else {
                                                // 若重试次数已 > 设置重试次数，则不重试,通过发送error来停止重试
                                                return Flowable.error(throwable);
                                            }
                                        } else {
                                            // 若发生的异常不属于I/O异常，则不重试,通过返回的Observable发送的事件 error事件 实现（可在观察者的onError（）中获取信息）
                                            return Flowable.error(throwable);
                                        }
                                    }
                                });
                            }
                        })
                        .subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

    /**
     * 切换线程操作
     *
     * @return Observable转换器
     */
    public static <T> ObservableTransformer<T, T> observeOnMainThread() {
        return new ObservableTransformer<T, T>() {
            // 可重试次数
            private int maxConnectCount = 3;
            // 当前已重试次数
            private int currentRetryCount = 0;
            // 重试等待时间
            private int waitRetryTime = 0;

            @Override
            public ObservableSource<T> apply(Observable<T> upstream) {

                return upstream//出错重连
                        .retryWhen(throwableObservable -> throwableObservable.flatMap((Function<Throwable, ObservableSource<?>>) throwable -> {
                            //当发生的异常 = 网络异常 = IO异常才选择重试
                            if (throwable instanceof IOException) {
                                // 限制重试次数
                                if (currentRetryCount < maxConnectCount) {
                                    // 记录重试次数
                                    currentRetryCount++;
                                    /**
                                     * 通过返回的Observable发送的事件next事件，从而使得retryWhen（）重订阅，实现重试功能
                                     * 延迟1段时间再重试,采用delay操作符 = 延迟一段时间发送，以实现重试间隔设置 每重试1次，增多延迟重试时间1s
                                     */
                                    // 设置等待时间
                                    waitRetryTime = 1000 + currentRetryCount * 500;
                                    Log.e(TAG, "重试次数:" + currentRetryCount + "--等待时间:" + waitRetryTime);

                                    return Observable.just(1).delay(waitRetryTime, TimeUnit.MILLISECONDS);
                                } else {
                                    // 若重试次数已 > 设置重试次数，则不重试通过发送error来停止重试
                                    return Observable.error(throwable);
                                }
                            } else {
                                // 若发生的异常不属于I/O异常，则不重试,通过返回的Observable发送的事件 error事件实现
                                return Observable.error(throwable);
                            }
                        }))
                        .subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

    /**
     * 统一线程处理
     *
     * @param <T> 指定的泛型类型
     * @return FlowableTransformer
     */
    public static <T> FlowableTransformer<T, T> flowableOnMainThread() {
        return new FlowableTransformer<T, T>() {
            // 可重试次数
            private int maxConnectCount = 3;
            // 当前已重试次数
            private int currentRetryCount = 0;
            // 重试等待时间
            private int waitRetryTime = 0;

            @Override
            public Publisher<T> apply(@NonNull Flowable<T> upstream) {
                return upstream
                        .retryWhen(new Function<Flowable<Throwable>, Publisher<?>>() {
                            @Override
                            public Publisher<?> apply(Flowable<Throwable> throwableFlowable) throws Exception {
                                return throwableFlowable.flatMap(new Function<Throwable, Publisher<?>>() {
                                    @Override
                                    public Publisher<?> apply(Throwable throwable) throws Exception {
                                        if (throwable instanceof IOException) {
                                            if (currentRetryCount < maxConnectCount) {
                                                currentRetryCount++;// 记录重试次数
                                                /**
                                                 * 实现重试
                                                 * 通过返回的Observable发送的事件 = next事件，从而使得retryWhen（）重订阅，最终实现重试功能
                                                 * 延迟1段时间再重试 delay操作符 = 延迟一段时间发送
                                                 * 在delay操作符的等待时间内设置 = 每重试1次，增多延迟重试时间1s
                                                 */
                                                waitRetryTime = 1000 + currentRetryCount * 1000;
                                                Log.e(TAG, "重试次数:" + currentRetryCount + "--等待时间:" + waitRetryTime);
                                                return Flowable.just(1).delay(waitRetryTime, TimeUnit.MILLISECONDS);
                                            } else {
                                                // 若重试次数已 > 设置重试次数，则不重试,通过发送error来停止重试
                                                return Flowable.error(throwable);
                                            }
                                        } else {
                                            // 若发生的异常不属于I/O异常，则不重试,通过返回的Observable发送的事件 error事件 实现（可在观察者的onError（）中获取信息）
                                            return Flowable.error(throwable);
                                        }
                                    }
                                });
                            }
                        })
                        .subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }


    /**
     * 绑定生命周期防止内存泄漏
     *
     * @param lifecycleOwner
     * @param <T>
     * @return
     */
    public static <T> AutoDisposeConverter<T> bindLifecycle(LifecycleOwner lifecycleOwner) {
        return AutoDispose.autoDisposable(
                AndroidLifecycleScopeProvider.from(lifecycleOwner)
        );
    }


}
